import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Jugador es el personaje principal a manejar por el usuario.
 * 
 * @author (Programacion Orientada a Objetos - Jose de Jesus Cervantes Hernandez)
 */
public class Jugador extends Actor
{
   /**
   * Arreglo imagenes del movimiento hacia la derecha.
   */
   private GreenfootImage [] WalkD;  
   
    /**
   * Arreglo imagenes del movimiento hacia la izquierda.
   */
   private GreenfootImage [] WalkI;
   
    /**
   * Arreglo imagenes del movimiento hacia arriiba a la derecha.
   */
   private GreenfootImage [] WalkAD;
   
     /**
   * Arreglo imagenes del movimiento hacia arriiba a la izquierda.
   */
   private GreenfootImage [] WalkAI;
   
   /**
    * Variable que referencia la primera plataforma.
    */
   private plataformaOne pl;
   
   /**
    * Variable que referencia la segunda plataforma.
    */
   private plataformTwo pll;
   
   /**
    * Variable que referencia la tercera plataforma.
    */
   private plataform3 plll;
   
   /**
    * Variable que referencia al enemigo lagarto.
    */
   private Enemigos ene;
   
   /**
    * Variable que referencia al enemigo barril.
    */
   private barril barr;
   
   /**
    * Variable que referencia al enemigo bomba.
    */
   private bombi bomba;
   
   /**
    * Variable que referencia el enemigo rinoceronte.
    */
   private rambi ramb;
   
   /**
    * Variable que referencia al objeto banana para cambiar de nivel.
    */
   private banana ban;
   
   /**
    * Variable del objeto vida que indica donde se dibujara el contador.
    */
   private vida vd;
   
   /**
    * Maxima cantidad de imagenes a leer para el movimiento a la derecha.
    */
   private static final int maxD = 4;               
   
   /**
    * Maxima cantidad de imagenes a leer para el movimiento a la izquierda.
    */
   private static final int maxI = 4;
   
   /**
    * Maxima cantidad de imagenes a leer para el movimiento arriba a la derecha.
    */
   private static final int maxAD = 5;
   
   /**
    * Maxima cantidad de imagenes a leer para el movimiento arriba a la izquierda.
    */
   private static final int maxAI = 5;
   
   /**
    * Constante que indica la direccion hacia arriba.
    */
   private static final int N = 2;   
   
   /**
    * Constante que indica la direccion hacia la derecha.
    */
   private static final int E = 3;                 
   
   /**
    * Constante que indica la direccion hacia la izquierda.
    */
   private static final int W = 4;
   
   /**
    * Constante que indica que el Jugador esta Quieto
    */
   private static final int Q = 0;
   
   /**
    * Numero de pasos que da por cada movimiento.   
    */
   private static final int pasos = 2;
   
   /**
    * Numero de vidas que tendra el Jugador.
    */
   private int lifes = 3;

   /**
    * Posicion actual en X del Jugador
    */
   private int X;                     
   
   /**
    * Posicion actual en Y del Jugador.
    */
   private int Y;                      
   
   /**
    * Posicion inicial en X del Jugador.
    */
   private int iniX;                    
   
   /**
    * Posicion inicial en Y del Jugador.
    */
   private int iniY;                    
   
   /**
    * Bandera para una referencia que se hace una vez.  
    */
   private int band=0;         
   
   /**
    * Indice para los ciclos FOR.
    */
   private int i;                
   
   /**
    * Variable que indica la direccion actual del Jugador.
    */
   private int dir;
   
   /**
    * Variable que inicializa el nivel.
    */
   private int niv = 1;
   
   /**
    * Variable que guarda la direccion anterior del Jugador.
    */
   private int lastDir;
   private int dirant;
   
   /**
    * Indice para su movimiento hacia abajo.
    */
   private int MA=1; 
   
   /**
    * Indice para su movimiento hacia arriba.
    */                              
   private int MN=1; 
   
   /**
    * Indice para su movimiento hacia la derecha.
    */
   private int ME=1;                         
   
   /**
    * Indice para su movimiento hacia la izquierda.
    */
   private int MW=1;  
   
   /**
    * Variable que indica el numero de brincos del jugador.
    */
   private int cb = 1;
  
   /**
    * Constructor de Jugador
    */
   public Jugador()
   {
     //  world = w;
       WalkD = new GreenfootImage[maxD];
       WalkI = new GreenfootImage[maxI];
       WalkAD = new GreenfootImage[maxAD];
       WalkAI = new GreenfootImage[maxAI];
       
       for(i=1; i<maxD ;i++)
        {
           WalkD[i] = new GreenfootImage("dk"+i+".png");  
        }
       
        for(i=1; i<maxI; i++)
       {
           WalkI[i] = new GreenfootImage("ik"+i+".png");
       }
       
       for(i=1; i<maxAD; i++)
       {
           WalkAD[i] = new GreenfootImage("bk"+i+".png");  
       }
              
       for(i=1; i<maxAI; i++)
       {
           WalkAI[i] = new GreenfootImage("bik"+i+".png");  
       }
        i=1;
        dir = Q;
   }
   
     /**
     * Constructor para la clase Bombi
     */
   public void act() 
    {
        if(band == 0)
        {
           iniX = getX();
           iniY = getY();
           band = 1;
        }
         
        X = this.getX();
        Y = this.getY();
        direccion();
        quitaVida();
        
    }
    
    /**
     * Metodo que regresa si se encontro el objeto plataforma 1.
     */
    public boolean buscaPlataforma1()
    {
        pl = (plataformaOne)this.getOneObjectAtOffset(0,0, plataformaOne.class);
        if(pl!=null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
     /**
     * Metodo que regresa si se encontro el objeto plataforma 2.
     */
    public boolean buscaPlataforma2()
    {
        pll = (plataformTwo)this.getOneObjectAtOffset(0,0, plataformTwo.class);
        if(pll!=null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
     /**
     * Metodo que regresa si se encontro el objeto plataforma 3.
     */
    public boolean buscaPlataforma3()
    {
        plll = (plataform3)this.getOneObjectAtOffset(0,0, plataform3.class);
        if(plll!=null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
    /**
     * Metodo que verifica el choque con el enemigo 1.
     */
    public boolean buscaChoque()
    {
        ene = (Enemigos)this.getOneObjectAtOffset(0,0,Enemigos.class);
        if(ene != null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
     /**
     * Metodo que verifica el choque con el enemigo 2.
     */
    public boolean buscaChoque2()
    {
        barr = (barril)this.getOneObjectAtOffset(0,0,barril.class);
        if(barr != null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
     /**
     * Metodo que verifica el choque con el enemigo 3. 
     */
    public boolean buscaChoque3()
    {
        bomba = (bombi)this.getOneObjectAtOffset(0,0,bombi.class);
        if(bomba != null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
      /**
     * Metodo que verifica el choque con el enemigo 4.
     */
    public boolean buscaChoque4()
    {
        ramb = (rambi)this.getOneObjectAtOffset(0,0,rambi.class);
        if(ramb != null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
     /**
     * Metodo que verifica el choque con la banana.
     */
    public boolean checkNiv()
    {
        ban = (banana)this.getOneObjectAtOffset(0,0,banana.class);
        if(ban != null)
        {
            return true;
        }
        else{
            return false;
        }
    }
    
    /**
     * Metodo que revisa que tecla esta presionada.
     */
    public void direccion()
    {
        if(Greenfoot.isKeyDown("right"))
        {
                dir = E;   
        }
        if(Greenfoot.isKeyDown("left"))
        {
                dir = W;
        }
        if(Greenfoot.isKeyDown("up") && cb <= 5)
        {
                dir = N;
        }
        puedeCaminar();
    }
    
    /**
     * Metodo que indica si el jugador puede caminar o no tiene ninguna plataforma.
     */
    public void puedeCaminar()
    {
        if(dir == N)
        {  
              brinca();
              cb++;
        }
        
        else if(buscaPlataforma1() || buscaPlataforma2()|| buscaPlataforma3()) 
        {
            cb = 0;
            mueve();
        }
        
        else
        {
            caida();
        }
    }
    
    /**
     * Metodo para mover al jugador en las plataformas.
     */
    public void mueve()
    {
       if(dir == E)
       {
           this.deleteI(0,0,1,0);
           this.setLocation(X+pasos,Y);
           this.setImage(WalkD [ME < maxD ? ME++ :(ME = 1)]);
           dirant = dir;
        }
       
       if(dir == W)
       {
           this.deleteI(0,0,0,1);
           this.setLocation(X-pasos,Y);
           this.setImage(WalkI [MW < maxI ? MW++ :(MW = 1)]); 
           dirant = dir;
       }
            
       if(dir == Q)
       {
            if(lastDir == N) 
               this.setImage(WalkAD[1]);
            if(lastDir == E) 
               this.setImage(WalkD[1]);
            if(lastDir == W) 
               this.setImage(WalkI[1]);
         }  
       lastDir = dir;
       dir = Q;
    }
    
    /**
     * Metodo para que el jugador pueda brincar.
     */
    public void brinca()
    {
       if(dirant == E)
       {
           this.deleteI(0,1,0,0);
           this.setLocation(X+10,Y-15);                
           this.setImage(WalkAD[ MN < maxAD ? MN ++: (MN = 1)]); 
           Greenfoot.playSound("ice01.dsp.wav");
          dir = E;
       }
       else if(dirant == W)
       {
           this.deleteI(0,1,0,0);
           this.setLocation(X-10,Y-15);                
           this.setImage(WalkAI[ MA < maxAI ? MA ++: (MA = 1)]);
           Greenfoot.playSound("ice01.dsp.wav");
           dir = W;
       }
    }
    
    /**
     * Metodo para la caida del jugador.
     */
    public void caida()
    {
        if(dirant == E)
        {
            this.deleteI(0,0,1,0);
            this.setLocation(X, Y+10);
            this.setImage(WalkAD [4]);
        }
        else if(dirant == W)
        {
            this.deleteI(0,0,1,0);
            this.setLocation(X, Y+10);
            this.setImage(WalkAI [4]);
        }
    }
    
    /**
     * Metodo que borra los indices de los arreglos de imagenes que ya no se esten usando
     * y necesitan volver a su valor de cero
     */
    public void deleteI(int s, int n, int e, int w)
    {
        if(n==0)
         { MN = 0;  }
        if(e==0)
         { ME = 0;  } 
        if(w==0)
         { MW = 0; }
    }
    
    /**
     * Metodo que sirve para aumentar las vidas del jugador
     */
    public void aumentaVida()
    {
        lifes++;
    }
    
    /**
     * En caso de que el jugador muera o caiga por un precipicio
     * ademas de ponerlo en la posicion inicial del nivel
     */
    
    public void disminuyeVida(int t)
    {
            lifes--;
            if(t == 0)
            {
                Greenfoot.playSound("kill.wav");
            }
            else if(t == 1)
            {
                Greenfoot.playSound("fall.wav");
            }
    }
    
    /**
     * Regresa el valor de las vidas ya que es un valor privado y solo asi se puede ver.
     */
    public int regresaVidas()
    {
        return lifes;
    }
    
    /**
     * Actualiza con parametro la cantidad de vida restante
     */      
    public void actualizaVidas(int v)
    {
        lifes = v;
    }
    
     /**
     * Metodo para quitarle una vida al Jugador cuando se cruza con algun enemigo. 
     */
    public void quitaVida()
    {
        if(buscaChoque() || buscaChoque2() || buscaChoque3() || buscaChoque4())
        {
            ((Mundo)this.getWorld()).restaVida(0);
             this.setLocation(iniX, iniY);
                     
        }
        else if(Y > 480)
        {
            ((Mundo)this.getWorld()).restaVida(1);
           this.setLocation(iniX, iniY);
        }
    }  
}

